#pragma once
#include "UtTestBase.h"
#include <atldef.h>


class CPUTCRT_API CUtException
{
public:
	enum EReportStatus
	{
		rsError,
		rsWarning,
		rsInconclusive,
	};

	enum EActionCode
	{
		acContinue = 0, //skip the current test
		acBreak,		//skip the rest tests of the current running test group
		acAbort			//abort test run
	};

	LPCSTR	m_lpFile;
	long	m_nLine;
	LPCSTR	m_lpFunction;
	LPWSTR	m_lpMessage;

	EReportStatus	m_eReportStatus;
	EActionCode		m_eActionCode;
	

	CUtException(LPCSTR lpFile, long nLine, LPCSTR lpFunction);
	CUtException(LPCSTR lpFile, long nLine, LPCSTR lpFunction, LPCSTR lpMessage);
	CUtException(LPCSTR lpFile, long nLine, LPCSTR lpFunction, LPCWSTR lpMessage);

	CUtException(LPCSTR lpFile, long nLine, LPCSTR lpFunction, EActionCode eActionCode, EReportStatus eReportStatus);
	CUtException(LPCSTR lpFile, long nLine, LPCSTR lpFunction, EActionCode eActionCode, EReportStatus eReportStatus, LPCSTR lpMessage);
	CUtException(LPCSTR lpFile, long nLine, LPCSTR lpFunction, EActionCode eActionCode, EReportStatus eReportStatus, LPCWSTR lpMessage);

	CUtException(const CUtException & r);
	~CUtException();
};

#define UT_ASSERT(condition) \
{ \
	BOOL __b_tempvr = condition; \
	DWORD __dwErrorCode_tempvr = GetLastError(); \
	ATLASSERT(__b_tempvr); \
	SetLastError(__dwErrorCode_tempvr); \
	if (!(__b_tempvr)) throw CUtException( __FILE__, __LINE__, __FUNCTION__); \
}


#define UT_ASSERT2(condition, message) \
{ \
	BOOL __b_tempvr = condition; \
	DWORD __dwErrorCode_tempvr = GetLastError(); \
	ATLASSERT(__b_tempvr); \
	SetLastError(__dwErrorCode_tempvr); \
	if (!(__b_tempvr)) throw CUtException( __FILE__, __LINE__, __FUNCTION__, message); \
}

#define UT_WARNING(condition, message) \
{ \
	BOOL __b_tempvr = condition; \
	DWORD __dwErrorCode_tempvr = GetLastError(); \
	ATLASSERT(__b_tempvr); \
	SetLastError(__dwErrorCode_tempvr); \
	if (!(__b_tempvr)) throw CUtException( __FILE__, __LINE__, __FUNCTION__, CUtException::acContinue, CUtException::rsWarning, message); \
}

#define UT_FAIL(message) \
{ \
	DWORD __dwErrorCode_tempvr = GetLastError(); \
	ATLASSERT(FALSE); \
	SetLastError(__dwErrorCode_tempvr); \
	throw CUtException( __FILE__, __LINE__, __FUNCTION__, message); \
}

#ifdef _UT
#define ut_private public
#define ut_protected public
#else
#define ut_private private
#define ut_protected protected
#endif